package com.authine.cloudpivot.ext.util;

import com.alibaba.cola.dto.Response;
import com.alibaba.cola.dto.SingleResponse;
import com.authine.cloudpivot.data.CriteriaQuery;
import com.authine.cloudpivot.data.Criterion;
import com.authine.cloudpivot.data.DynamicCrudRepository;
import com.authine.cloudpivot.data.condition.Order;
import com.authine.cloudpivot.data.condition.Sortable;
import com.authine.cloudpivot.data.criterion.Op;
import com.authine.cloudpivot.data.support.*;
import com.authine.common.json.JsonUtils;
import com.authine.hermes.app.launcher.service.BOService;
import com.authine.mvp.app.launcher.common.TableHelper;
import com.authine.mvp.app.launcher.domain.utills.ApplicationContextUtils;
import com.authine.mvp.app.launcher.dto.bo.cmd.BatchDeleteBOCmd;
import com.authine.mvp.app.launcher.dto.bo.cmd.CreateBOCmd;
import com.authine.mvp.app.launcher.dto.bo.cmd.DeleteBOCmd;
import com.authine.mvp.app.launcher.dto.bo.cmd.UpdateBOCmd;
import com.authine.mvp.app.launcher.dto.bo.query.ListBOQuery;
import com.authine.mvp.app.launcher.dto.bo.query.LoadBOQuery;
import com.authine.mvp.app.launcher.dto.bo.query.expression.*;
import com.authine.mvp.app.launcher.dto.bo.response.BO;
import com.authine.mvp.app.launcher.dto.bo.response.BOList;
import com.authine.mvp.app.launcher.utils.BOUtils;
import com.authine.mvp.app.launcher.utils.ExpressionUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpMethod;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;

@Slf4j
public class BoServiceUtils {
    private static ExpressionUtils expressionUtils =  ApplicationContextUtils.getBean(ExpressionUtils.class);
    private static TableHelper tableHelper =  ApplicationContextUtils.getBean(TableHelper.class);
    private static DynamicCrudRepository dynamicCrudRepository =  ApplicationContextUtils.getBean(DynamicCrudRepository.class);
    private static BOService boService =  ApplicationContextUtils.getBean(BOService.class);

    /**
     * 列表接口
     * @param condition 过滤条件
     * @param pageSize 每页显示条数
     * @param pageIndex 分页页码
     * @param schemaCode 模型编码
     * @return 集合
     */
    public static SingleResponse<BOList> easyList(Condition condition, Integer pageSize, Integer pageIndex, String schemaCode){
        //列表查询接口参数
        ListBOQuery listBOQuery = new ListBOQuery();
        listBOQuery.setSchemaCode(schemaCode);
        if(condition != null) {
            listBOQuery.setCondition(condition);
        }
        if(pageIndex == null){
            pageIndex = -1;
        }
        listBOQuery.setPageIndex(pageIndex);
        if(pageSize != null) {
            listBOQuery.setPageSize(pageSize);
        }
        return boService.list(listBOQuery);
    }

    public static SingleResponse<BOList> findListBySimple(String schemaCode, String columnName, Object columnValue, Operator operator) {
        ListBOQuery listQry = new ListBOQuery();
        listQry.setPageIndex(-1);
        listQry.setSchemaCode(schemaCode);
        SimpleCondition condition = new SimpleCondition(columnName, operator, columnValue);
        listQry.setCondition(condition);
        SingleResponse<BOList> list = boService.list(listQry);
        log.info("BoServiceUtils findListBySimple list:{}" , list);
        if(!list.isSuccess()){
            throw BoUtils.bizException("模型列表查询出错："+schemaCode+":"+list.getErrMessage());
        }
        return list;
    }

    public static SingleResponse<BOList> findListBySimpleAppointPageSize(String schemaCode, String columnName, Object columnValue, Operator operator,Integer pageSize) {
        ListBOQuery listQry = new ListBOQuery();
        listQry.setSchemaCode(schemaCode);
        listQry.setPageSize(pageSize);
        SimpleCondition condition = new SimpleCondition(columnName, operator, columnValue);
        listQry.setCondition(condition);
        SingleResponse<BOList> list = boService.list(listQry);
        log.info("BoServiceUtils findListBySimple list:{}" , list);
        if(!list.isSuccess()){
            throw BoUtils.bizException("模型列表查询出错："+schemaCode+":"+list.getErrMessage());
        }
        return list;
    }

    public static SingleResponse<BOList> findListBySimpleRest(String url,String schemaCode, String columnName, Object columnValue, Operator operator) {
        ListBOQuery listQry = new ListBOQuery();
        listQry.setPageIndex(-1);
        listQry.setSchemaCode(schemaCode);
        SimpleCondition condition = new SimpleCondition(columnName, operator, columnValue);
        listQry.setCondition(condition);
        //Response list = RestTemplateUtil.rest(url, listQry, HttpMethod.POST);
        Response list = null;
        //SingleResponse<BOList> list = boService.list(listQry);
        log.info("BoServiceUtils findListBySimple list:{}" , list);
        if(!list.isSuccess()){
            throw BoUtils.bizException("模型列表查询出错："+schemaCode+":"+list.getErrMessage());
        }
        return (SingleResponse)list;
    }


    public static SingleResponse<BOList> findListByCondition( String schemaCode, Condition condition) {
        ListBOQuery listQry = new ListBOQuery();
        listQry.setPageIndex(-1);
        listQry.setSchemaCode(schemaCode);
        listQry.setCondition(condition);
        SingleResponse<BOList> list = boService.list(listQry);
        log.info("BoServiceUtils findListBySimple list:{}" , list);
        if(!list.isSuccess()){
            throw BoUtils.bizException("模型列表查询出错："+schemaCode+":"+list.getErrMessage());
        }
        return list;
    }

    public static SingleResponse<BOList> findListByConditionPageSize(String schemaCode, Condition condition,int pageSize) {
        ListBOQuery listQry = new ListBOQuery();
        listQry.setSchemaCode(schemaCode);
        listQry.setPageSize(pageSize);
        listQry.setCondition(condition);
        SingleResponse<BOList> list = boService.list(listQry);
        log.info("BoServiceUtils findListBySimple list:{}" , list);
        if(!list.isSuccess()){
            throw BoUtils.bizException("模型列表查询出错："+schemaCode+":"+list.getErrMessage());
        }
        return list;
    }

    public static SingleResponse<BOList> findListByCondition(String schemaCode, Condition condition,int pageSize,int pageIndex) {
        ListBOQuery listQry = new ListBOQuery();
        listQry.setPageIndex(pageIndex);
        listQry.setPageSize(pageSize);
        listQry.setSchemaCode(schemaCode);
        listQry.setCondition(condition);
        SingleResponse<BOList> list = boService.list(listQry);
        log.info("BoServiceUtils findListBySimple list:{}" , list);
        if(!list.isSuccess()){
            throw BoUtils.bizException("模型列表查询出错："+schemaCode+":"+list.getErrMessage());
        }
        return list;
    }

    public static SingleResponse<BOList> findListByAnd( String schemaCode, String[] columnNames, String[] columnValues, Operator[] operators) {
        ListBOQuery listQry = new ListBOQuery();
        listQry.setPageIndex(-1);
        listQry.setSchemaCode(schemaCode);
        ComplexCondition complexCondition = new ComplexCondition();
        complexCondition.setNature(Nature.AND);
        for (int i = 0; i < columnNames.length; i++) {
            SimpleCondition condition = new SimpleCondition(columnNames[i], operators[i], columnValues[i]);
            complexCondition.getConditions().add(condition);
        }
        listQry.setCondition(complexCondition);
        return boService.list(listQry);
    }

    public static SingleResponse<BO> loadByBizObjectId(String schemaCode, String bizObjectId) {
        try {
            LoadBOQuery loadBOQuery = new LoadBOQuery();
            loadBOQuery.setSchemaCode(schemaCode);
            loadBOQuery.setBizObjectId(bizObjectId);
            return boService.load(loadBOQuery);
        } catch (Exception e) {
            log.error("loadByBizObjectId Exception", e);
        }
        SingleResponse<BO> singleResponse = SingleResponse.of(new BO());
        singleResponse.setSuccess(false);
        return singleResponse;
    }

    public static SingleResponse<BO> delete(String schemaCode, String bizObjectId) {
        try {
            DeleteBOCmd deleteBOCmd = new DeleteBOCmd();
            deleteBOCmd.setSchemaCode(schemaCode);
            deleteBOCmd.setBizObjectId(bizObjectId);
             boService.delete(deleteBOCmd);
        } catch (Exception e) {
            log.error("loadByBizObjectId Exception", e);
        }
        SingleResponse<BO> singleResponse = SingleResponse.of(new BO());
        singleResponse.setSuccess(false);
        return singleResponse;
    }



    public static SingleResponse<Boolean> batchDeleteByBizObjectIds(String schemaCode, List<String> bizObjectIds) {
        BatchDeleteBOCmd batchDeleteBOCmd = new BatchDeleteBOCmd();
        batchDeleteBOCmd.setSchemaCode(schemaCode);
        batchDeleteBOCmd.setBizObjectIds(bizObjectIds);
        Response response = boService.batchDelete(batchDeleteBOCmd);
        if(response.isSuccess()){
            return SingleResponse.of(Boolean.TRUE);
        }else{
            return SingleResponse.of(Boolean.FALSE);
        }
    }
    public static SingleResponse<BO> createBo(String schemaCode, Map<String, Object> data){
        CreateBOCmd createBOCmd = new CreateBOCmd();
        createBOCmd.setSchemaCode(schemaCode);
        createBOCmd.setData(Collections.singletonList(data));
        log.info("新增参数:"+ BoUtils.toJsonString(createBOCmd));
        SingleResponse<BO> boResponse = boService.create(createBOCmd);
        if(!boResponse.isSuccess()){
            throw BoUtils.bizException("创建模型出错："+schemaCode+":"+boResponse.getErrMessage());
        }
        return boResponse;
    }


    public static SingleResponse<BO> batchCreateBo(String schemaCode, List<Map<String, Object>> dataList){
        CreateBOCmd createBOCmd = new CreateBOCmd();
        createBOCmd.setSchemaCode(schemaCode);
        createBOCmd.setData(dataList);
        log.info("新增参数:"+ BoUtils.toJsonString(createBOCmd));
        SingleResponse<BO> boResponse = boService.create(createBOCmd);
        if(!boResponse.isSuccess()){
            throw BoUtils.bizException("创建模型出错："+schemaCode+":"+boResponse.getErrMessage());
        }
        return boResponse;
    }


    public static SingleResponse<BO> updateBo(String schemaCode, Map<String, Object> data){
        UpdateBOCmd updateBOCmd = new UpdateBOCmd();
        updateBOCmd.setSchemaCode(schemaCode);
        updateBOCmd.setData(Collections.singletonList(data));
        log.info("修改参数:"+ BoUtils.toJsonString(updateBOCmd));
        SingleResponse<BO> updateResponse = boService.update(updateBOCmd);
        if(!updateResponse.isSuccess()){
            throw BoUtils.bizException("修改模型出错："+schemaCode+":"+updateResponse.getErrMessage());
        }
        return updateResponse;
    }

    public static SingleResponse<BO> batchUpdateBo(String schemaCode, List<Map<String, Object>> data){
        UpdateBOCmd updateBOCmd = new UpdateBOCmd();
        updateBOCmd.setSchemaCode(schemaCode);
        updateBOCmd.setData(data);
        log.info("修改参数:"+ BoUtils.toJsonString(updateBOCmd));
        SingleResponse<BO> updateResponse = boService.update(updateBOCmd);
        if(!updateResponse.isSuccess()){
            throw BoUtils.bizException("修改模型出错："+schemaCode+":"+updateResponse.getErrMessage());
        }
        return updateResponse;
    }

    public static SingleResponse<BO> saveBo(String schemaCode, Map<String, Object> data){
        CreateBOCmd cmd = new CreateBOCmd();
        cmd.setSchemaCode(schemaCode);
        cmd.setData(Collections.singletonList(data));
        log.info("数据新增参数:"+ BoUtils.toJsonString(cmd));
        return boService.create(cmd);
    }

    public static Criterion filterDeleted(Criterion criterion) {
        if (criterion == null) {
            return Q.it(BOUtils.DELETED, Op.EQ, Boolean.FALSE);
        }
        return Q.and(Q.it(BOUtils.DELETED, Op.EQ, Boolean.FALSE), criterion);
    }

    public static SingleResponse<BOList> sortQuery(ListBOQuery query,Sortable sortable){
        if(Objects.isNull(sortable)){
           return boService.list(query);
        }
        BOList boList = new BOList();
        Criterion criterion = expressionUtils.condition2Criterion(query.getCondition(), query.getSchemaCode());
        criterion = filterDeleted(criterion);
        log.info("schemaCode = {},criterion = {}", query.getSchemaCode(), JsonUtils.toJson(criterion));
        String tableName = tableHelper.getTableName(query.getSchemaCode());
        long count = dynamicCrudRepository.count(CriteriaQueryImpl.builder().tableName(tableName).criterion(criterion).build());
        if (count <= 0) {
            return SingleResponse.of(boList);
        }
        boList.setTotal((int) count);
        CriteriaQueryImpl.CriteriaQueryImplBuilder builder = CriteriaQueryImpl.builder();
        if (query.getPageIndex() >= 0) {
            builder.pageable(new PageableImpl(query.getPageIndex() * query.getPageSize(), query.getPageSize()));
        }
        builder.tableName(tableName).criterion(criterion).sortable(sortable);
        CriteriaQuery criteriaQuery = builder.build();
        List<Map<String, Object>> data = dynamicCrudRepository.findAll(criteriaQuery);
        boList.setData(data);
        return SingleResponse.of(boList);
    }
}
